package cn.icare.cms.controller;

import cn.icare.cms.*;
import cn.icare.cms.config.WxInfoConfig;
import cn.icare.cms.dao.po.*;
import cn.icare.cms.impl.PromotionServiceImpl;
import cn.icare.cms.model.enums.OrderStatusEnum;
import cn.icare.cms.model.ro.*;
import cn.icare.cms.model.vo.rest.MsgDatasVO;
import cn.icare.cms.model.vo.rest.RespMsgVO;
import cn.icare.cms.model.wx.ro.WxConfig;
import cn.icare.cms.model.wx.ro.WxPayInfoRo;
import cn.icare.cms.model.wx.vo.WxPayInfoVo;
import cn.icare.cms.sync.SyncOrderService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname ItemOrderController
 * @Description TODO
 * @Date 2020/3/16 16:59
 * @Created by Administrator
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/rest/personal/itemorder")
@Api(tags = "REST订单")
public class ItemOrderController extends BaseController {

    @Autowired
    private SyncOrderService syncOrderService;

    @Autowired
    private ShopCartService shopCartService;

    @Autowired
    private ItemStoreService itemStoreService;

    @Autowired
    private MemberAddressService memberAddressService;

    @Autowired
    private PromotionService promotionService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private WxInfoConfig wxInfoConfig;

    @Autowired
    private WxService wxService;


    private final Logger logger = LoggerFactory.getLogger(ItemOrderController.class);

    /**
     * URL:http://{ip}:{port}/rest/area
     * method:POST
     *
     * @param ro
     * @return
     */
    @PostMapping()
    @ApiOperation(value = "新增订单", notes = "新增订单")
    public ResponseEntity<RespMsgVO> createOne(@RequestBody AddItemOrderRO ro, HttpServletRequest request) {
        Long memberId = 0L;
        Member member = this.getCurrentUser(request);

        if (member != null) {
            memberId = member.getId();
        }
        if (memberId <= 0) {
            return super.getRespFail("会员身份验证信息不正确");
        }
        //区域Id
        Long areaId = changeStoreAreaId(ro.getAreaId());
        int itemnum = ro.getShopcartIds().size();
        //先检查购物车是否有此商品
        MsgDatasVO msgDatasVO = shopCartService.getListByIds(ro.getShopcartIds(), memberId, areaId);
        if (msgDatasVO == null || msgDatasVO.getTotal() < itemnum) {

            return super.getRespFail("有部分商品已经失效，请刷新购物车");
        } else {
            List<Map<String, Object>> itemList = (List<Map<String, Object>>) msgDatasVO.getDatas();

            Long nowcount = itemList.stream().filter((item) -> {
                return "1".equals(item.get("status").toString());
            }).count();
            if (itemnum > nowcount) {
                return super.getRespFail("有部分商品已经失效，请刷新购物车");
            } else {
                //收货信息
                MemberAddress address = memberAddressService.getOne(ro.getAddressId());
                if (address == null) {
                    return super.getRespFail("对不起,订单收货地址不存");
                }
                AddOrderRo orderRo = new AddOrderRo();

                //收货地址
                OrderAddressRo addressRo = new OrderAddressRo();
                addressRo.setName(address.getName());
                addressRo.setMobile(address.getMobile());
                addressRo.setDistrict(address.getAreacode());
                addressRo.setAddress(String.format("%s %s", address.getGpsponit(), address.getAddress()));
                orderRo.setAddress(addressRo);

                orderRo.setCouponid(ro.getCouponId());//优惠券Id

                List<OrderItemRo> itemRoList = new ArrayList<>();
                BigDecimal orderTotal = new BigDecimal("0.00");//订单总价

                List<Map<String, Object>> tempSaveStoreList = new LinkedList<>();

                //先更新库存
                itemList.forEach((item) -> {
                    Long itemId = Long.parseLong(item.get("itemid").toString());
                    Integer itemNum = Integer.valueOf(item.get("num").toString());
                    BigDecimal itemPrice = new BigDecimal(item.get("price").toString());
                    OrderItemRo itemRo;
                    BigDecimal itemtotal = new BigDecimal("0.00");
                    boolean success = false;
                    //开始减库存
                    Object promObj = item.get("promid");
                    Integer storeId = 0;
                    Integer type = 1; //类型1-促销商品 0-普通商品
                    if (promObj != null) {
                        //促销商品
                        storeId = Integer.parseInt(promObj.toString());

                        success = this.promotionService.subtractItemNum(itemId, Integer.parseInt(promObj.toString()), itemnum);
                    } else {
                        //普通商品
                        type = 0;
                        storeId = getStoreId(itemId, areaId, itemNum, address.getLon(), address.getLat());
                        success = this.itemStoreService.subtractItemNum(itemId, storeId, itemnum);
                    }
                    //减库存成功
                    if (success) {
                        itemRo = new OrderItemRo();
                        itemRo.setItemid(itemId);
                        itemRo.setNum(itemNum);
                        itemRo.setPrice(itemPrice);
                        itemRo.setPicurl(item.get("image").toString());
                        itemRo.setTitle(item.get("title").toString());
                        itemtotal = itemPrice.multiply(new BigDecimal(itemNum));
                        itemRo.setTotal(itemtotal);
                        itemRo.setStoredid(storeId);
                        itemRo.setType(type);
                        itemRoList.add(itemRo); //加入到订单商品列表中

                        HashMap tempMap = new HashMap<String, Object>();
                        tempMap.put("itemId", itemId);
                        tempMap.put("type", type);
                        tempMap.put("storeId", storeId);
                        tempMap.put("itemNum", itemNum);
                        tempSaveStoreList.add(tempMap);

                    } else {
                        logger.warn("商品(Id:%s)%s库存少于:%s,不能下单", itemId, item.get("title").toString(), itemnum);
                    }
                });
                if (itemRoList == null || itemRoList.size() == 0) {
                    return super.getRespFail("商品已经抢购完");
                } else {
                    //保存订单信息，采用异步
                    //通过java stream求和计算出订单总金额
                    orderTotal = itemRoList.stream().map(x -> x.getTotal()).reduce(BigDecimal.ZERO, BigDecimal::add);
                    orderRo.setItems(itemRoList); //订单商品
                    orderRo.setMemo(ro.getMemo()); //订单备注信息
                    orderRo.setExpresstime(ro.getExpresstime()); //配送时间
                    orderRo.setExpressfee(ro.getExpressfee());//配送费
                    orderRo.setMemberid(memberId);
                    orderRo.setMembername(member.getUsername());
                    orderRo.setSumamount(orderTotal); //商品原价总金额
                    Long result = this.syncOrderService.createNewOrder(orderRo, ro.getCouponId());
                    if (result > 0) {
                        //删除购物车记录
                        this.shopCartService.deleteBatch(ro.getShopcartIds(), memberId);
                        return super.getRespOk(result);
                    } else {
                        //订单创建有错误
                        //库存需要增加回去
                        if (tempSaveStoreList != null && tempSaveStoreList.size() > 0) {
                            tempSaveStoreList.forEach((item) -> {
                                Integer type = Integer.valueOf(item.get("type").toString());
                                Integer num = Integer.valueOf(item.get("itemNum").toString());
                                Integer storeId = Integer.valueOf(item.get("storeId").toString());
                                Long itemId = Long.valueOf(item.get("itemId").toString());
                                if (type == 1) {
                                    this.promotionService.addItemNum(itemId, storeId, num);
                                } else {
                                    this.itemStoreService.addItemNum(itemId, storeId, num);
                                }
                            });
                        }
                        return super.getRespFail("订单创建失败，请稍候操作");
                    }
                }
            }
        }

    }

    @GetMapping()
    @ApiOperation(value = "查询会员订单列表", notes = "查询会员订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "status", value = "状态：-1、全部,0、待付款，1、待发货，2、待收货，3、待评价，4、退款中，5、已完成，6、已取消，7、已退款",
                    required = true, defaultValue = "1", paramType = "query", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "beginTime", value = "开始时间", required = false, paramType = "query", dataTypeClass = String.class),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = false, paramType = "query", dataTypeClass = String.class),
            @ApiImplicitParam(name = "pageNum", value = "页码", required = true, defaultValue = "1", paramType = "query", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "pageSize", value = "每页记录数", required = true, defaultValue = "20", paramType = "query", dataTypeClass = Integer.class)
    })
    public ResponseEntity<RespMsgVO> getList(Integer status, Integer pageNum,
                                             String beginTime,
                                             String endTime,
                                             Integer pageSize
            , HttpServletRequest request) {
        Long memberId = this.getCurrentUserId(request);
        if (memberId <= 0) {
            return super.getRespFail("会员身份验证信息不正确");
        }
        SearchOrderListRo ro = new SearchOrderListRo();
        ro.setMemberId(memberId);
        ro.setBeginTime(beginTime);
        ro.setEndTime(endTime);
        ro.setPageNum(pageNum);
        ro.setPageSize(pageSize);
        ro.setStatus(status);
        return super.getRespOk(orderService.getList(ro));
    }

    /**
     * URL:http://{ip}:{port}/rest/area
     * method:POST
     *
     * @param ro
     * @return
     */
    @PostMapping("/pay")
    @ApiOperation(value = "订单付款", notes = "订单付款")
    public ResponseEntity<RespMsgVO> payOrder(@RequestBody PayOrderRo ro, HttpServletRequest request) {

        if (ro.getOrderId() > 0) {
            Order order = this.orderService.getOne(ro.getOrderId());
            if (order != null) {
                WxConfig wxConfig = new WxConfig();
                wxConfig.setAppid(wxInfoConfig.getAppid());
                wxConfig.setSecret(wxInfoConfig.getSecret());
                wxConfig.setWxapi(wxInfoConfig.getWxapi());
                String openId = this.wxService.getOpenIdByCode(wxConfig, ro.getCode());
                if (StringUtil.isEmpty(openId)) {
                    return super.getRespFail("微信授权失败，请重试");
                }
                //        String openId ="ohLSX5Pk0kWqKW9eRQaMeqon1KjE"; //TODO 测试代码
                WxPayInfoRo wxPayInfoRo = new WxPayInfoRo();
                wxPayInfoRo.setOpenid(openId);
                wxPayInfoRo.setAttach(order.getId().toString());
                wxPayInfoRo.setAppid(wxInfoConfig.getAppid());
                wxPayInfoRo.setMch_id(wxInfoConfig.getMch_id());
                wxPayInfoRo.setDevice_info("web");
                wxPayInfoRo.setNonce_str(PayUtil.makeUUID(32));
                wxPayInfoRo.setBody("逛呗买菜-订单支付");
                wxPayInfoRo.setNotify_url(wxInfoConfig.getOrderpaycallapi());
                wxPayInfoRo.setOut_trade_no(order.getCode());
                wxPayInfoRo.setTotal_fee(PayUtil.moneyToIntegerStr(order.getAmmount()));
                wxPayInfoRo.setSpbill_create_ip(PayUtil.getLocalIp());
                wxPayInfoRo.setTrade_type("JSAPI");
                String sign = PayUtil.createSignByObject(wxPayInfoRo, wxInfoConfig.getMch_key());
                wxPayInfoRo.setSign(sign);
                WxPayInfoVo result = this.wxService.sendPay(wxInfoConfig.getOrderpayapi(), wxPayInfoRo);
                if (result != null) {
                    if (StringUtil.isNotEmpty(result.getPrepay_id())) {
                        Map<String, String> data = new HashMap<>();
                        data.put("appId", wxPayInfoRo.getAppid());
                        data.put("timeStamp", DateUtil.getCurrentDateStamp());
                        data.put("nonceStr", wxPayInfoRo.getNonce_str());
                        data.put("package", String.format("prepay_id=%s", result.getPrepay_id()));
                        data.put("signType", "MD5");
                        String paySign = PayUtil.createSignByObject(data, wxInfoConfig.getMch_key());
                        data.put("paySign", paySign);
                        this.logger.info("paySign:" + paySign);
                        //订单支付过程记录保存
                        syncOrderService.saveOrderPayingLog(order);
                        return super.getRespOk(data);
                    } else {
                        String error = "";
                        if (StringUtil.isNotEmpty(result.getErr_code_des())) {
                            error = result.getErr_code_des();
                        } else if (StringUtil.isNotEmpty(result.getReturn_msg())) {
                            error = result.getReturn_msg();
                        }
                        this.logger.error("生成预支付交易单失败:" + error);
                        return super.getRespFail(error);
                    }


                } else {
                    return super.getRespFail("支付失败");
                }
            } else {
                return super.getRespFail("传入的订单Id不存在");
            }
        } else {
            return super.getRespFail("传入的订单Id不能为空或0");
        }
    }


    /**
     * URL:http://{ip}:{port}/rest/personal/itemorder/{id}
     * method:GET
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation(value = "查询单个订单详情", notes = "查询单个订单详情")
    public ResponseEntity<RespMsgVO> getOne(@PathVariable("id") Long id) {
        return super.getRespOk(this.orderService.getDetail(id));
    }


    @PostMapping("/cancel")
    @ApiOperation(value = "取消订单", notes = "取消订单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单Id", required = true, paramType = "query", dataTypeClass = MultipartFile.class)
    })
    public ResponseEntity<RespMsgVO> cancelOne(Long id, HttpServletRequest request) {

        Long memberId = this.getCurrentUserId(request);
        if (memberId <= 0) {
            return super.getRespFail("会员身份验证信息不正确");
        }

        Order order = this.orderService.getOne(id);
        if (order != null && order.getMemberid() == memberId) {

            Integer status = order.getStatus();
            if (status <= 1) {
                boolean result = false;
                if (status == 1) {
                    //已经付款需要退款操作
                    //1-向微信发送退款申请

                    WxPayInfoRo wxPayInfoRo = new WxPayInfoRo();

                    wxPayInfoRo.setAppid(wxInfoConfig.getAppid());
                    wxPayInfoRo.setMch_id(wxInfoConfig.getMch_id());

                    wxPayInfoRo.setNonce_str(PayUtil.makeUUID(32));

                    wxPayInfoRo.setNotify_url(wxInfoConfig.getRefundcallapi());
                    wxPayInfoRo.setOut_trade_no(order.getCode());
                    wxPayInfoRo.setOut_refund_no(order.getCode()); //商户退款单号

                    wxPayInfoRo.setTotal_fee(PayUtil.moneyToIntegerStr(order.getAmmount()));
                    wxPayInfoRo.setRefund_fee(wxPayInfoRo.getTotal_fee());
                    wxPayInfoRo.setNotify_url(wxInfoConfig.getRefundcallapi());
                    String sign = PayUtil.createSignByObject(wxPayInfoRo, wxInfoConfig.getMch_key());
                    wxPayInfoRo.setSign(sign);
                    WxPayInfoVo wxResult = this.wxService.refund(wxInfoConfig.getRefundapi(), wxPayInfoRo, wxInfoConfig.getCert_path());
                    //2-将订单状态更新为退款中
                    if (wxResult != null) {
                        if ("SUCCESS".equals(wxResult.getResult_code())) {
                            result = this.orderService.updateStatus(id, OrderStatusEnum.REFUNDING.getCode());
                        } else {
                            String error = "";
                            if (StringUtil.isNotEmpty(wxResult.getErr_code_des())) {
                                error = wxResult.getErr_code_des();
                            } else if (StringUtil.isNotEmpty(wxResult.getReturn_msg())) {
                                error = wxResult.getReturn_msg();
                            }
                            this.logger.error("取消订单操作失败:" + error);
                            return super.getRespFail(error);
                        }
                    } else {
                        return super.getRespFail("退款申请操作失败，请稍候再试");
                    }
                } else {
                    //直接取消
                    result = this.orderService.updateStatus(id, OrderStatusEnum.CANCEL.getCode());
                    //商品库存恢复
                    if (result) {
                        result = this.resumeOrderItemStore(id);
                    }
                }
                if (result) {
                    String msg = "订单取消成功";
                    if (status == 1) {
                        msg += ",订单金额将原路退回到您的付款帐号中，请稍候查询";
                    }
                    return super.getRespOk(msg);
                } else {
                    return super.getRespFail("对不起，订单取消失败，请稍候再试");

                }
            } else if (status == OrderStatusEnum.CANCEL.getCode()) {
                return super.getRespFail("对不起，请不要重复操作");
            } else {
                return super.getRespFail("对不起，订单已经配送中");
            }
        } else {
            return super.getRespFail("对不起，订单信息不存在");
        }

    }


    @PostMapping("/arrivalFinished")
    @ApiOperation(value = "订单送达接口", notes = "订单送达接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单Id", required = true, paramType = "query", dataTypeClass = MultipartFile.class)
    })
    public ResponseEntity<RespMsgVO> arrivalFinished(Long id, HttpServletRequest request) {

        Long memberId = this.getCurrentUserId(request);
        if (memberId <= 0) {
            return super.getRespFail("会员身份验证信息不正确");
        }

        Order order = this.orderService.getOne(id);
        if (order != null) {
            Integer status = order.getStatus();
            boolean result = false;
            String error = "";
            if (status == OrderStatusEnum.SENDING.getCode()) {
                result = this.orderService.updateArrivalFinished(id, memberId);
            } else {
                error = "操作失败，订单状态异常:" + status;
            }
            if (result) {
                return super.getRespOk();
            } else {
                this.logger.error("arrivalFinished: 异常," + error);
                return super.getRespFail("操作失败请稍候再试");
            }
        } else {
            return super.getRespFail("对不起，订单信息不存在");
        }

    }


//    @PostMapping("/confirm")
//    @ApiOperation(value = "订单确认收货接口", notes = "订单确认收货接口")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "id", value = "订单Id", required = true, paramType = "query", dataTypeClass = MultipartFile.class)
//    })
//    public ResponseEntity<RespMsgVO> confirmOne(Long id, HttpServletRequest request) {
//
//        Long memberId = this.getCurrentUserId(request);
//        if (memberId <= 0) {
//            return super.getRespFail("会员身份验证信息不正确");
//        }
//
//        Order order = this.orderService.getOne(id);
//        if (order != null && order.getMemberid() == memberId) {
//            Integer status = order.getStatus();
//            boolean result = false;
//            String error = "";
//            if (status == OrderStatusEnum..getCode()) {
//                //待评价
//                result = this.orderService.updateStatus(id, OrderStatusEnum.WAIT_COMMENT.getCode());
//            } else {
//                error = "操作失败，订单状态异常:" + status;
//            }
//            if (result) {
//                return super.getRespOk();
//            } else {
//                this.logger.error("confirmOne: 异常," + error);
//                return super.getRespFail("操作失败请稍候再试");
//            }
//        } else {
//            return super.getRespFail("对不起，订单信息不存在");
//        }
//
//    }


    //# region private
    private Integer getStoreId(Long itemId, Long areaId, Integer num, Double memAddresLon, Double memAddressLat) {
        Integer storeId = 0;
        List<Map<String, Object>> storeList = this.itemStoreService.getItemStoreList(itemId, areaId, num);
        if (storeList != null && storeList.size() > 0) {
            if (storeList.size() == 1) {
                storeId = Integer.valueOf(storeList.get(0).get("storeid").toString());
            } else {
                //TODO 多个仓库，需要根据创建的经纬度来计算更近的
            }
        }
        return storeId;
    }
    //#endregion
}
